#include "Vector3.h"
#include <math.h>
#include <stdio.h>

const double Vector3::ZERO = 0.0000001;

Vector3::Vector3(const double x, const double y, const double z)
{
	m_fX = x;
	m_fY = y;
	m_fZ = z;
}

Vector3::Vector3(const Vector3& vector)
{
	m_fX = vector.m_fX;
	m_fY = vector.m_fY;
	m_fZ = vector.m_fZ;
}

void Vector3::setX(const double x)
{
	m_fX = x;
}

void Vector3::setY(const double y)
{
	m_fY = y;
}

void Vector3::setZ(const double z)
{
	m_fZ = z;
}

double Vector3::x() const
{
	return m_fX;
}

double Vector3::y() const
{
	return m_fY;
}

double Vector3::z() const
{
	return m_fZ;
}

Vector3 Vector3::yzx() const
{
	return Vector3(m_fY, m_fZ, m_fX);
}

Vector3 Vector3::zxy() const
{
	return Vector3(m_fZ, m_fX, m_fY);
}

const Vector3 Vector3::operator+(const Vector3& vector) const
{
	return Vector3(m_fX + vector.m_fX, m_fY + vector.m_fY, m_fZ + vector.m_fZ);
}

const Vector3 Vector3::operator-(const Vector3& vector) const
{
	return Vector3(m_fX - vector.m_fX, m_fY - vector.m_fY, m_fZ - vector.m_fZ);
}

const Vector3 Vector3::operator-() const
{
	return Vector3(-m_fX, -m_fY, -m_fZ);
}

double Vector3::operator*(const Vector3& vector) const
{
	double result = 0.0;
	result += m_fX * vector.m_fX;
	result += m_fY * vector.m_fY;
	result += m_fZ * vector.m_fZ;

	return result;
}

const Vector3 Vector3::cross(const Vector3& vector) const
{
	double x1 = m_fX;
	double y1 = m_fY;
	double z1 = m_fZ;

	double x2 = vector.m_fX;
	double y2 = vector.m_fY;
	double z2 = vector.m_fZ;

	return Vector3(y1 * z2 - y2 * z1,
					 x2 * z1 - x1 * z2,
					 x1 * y2 - x2 * y1);
}

const Vector3 Vector3::operator*(double factor) const
{
	return Vector3(m_fX * factor, m_fY * factor, m_fZ * factor);
}

const Vector3 Vector3::operator/(double factor) const
{
	if (factor < ZERO)
		return Vector3(m_fX, m_fY, m_fZ);
	else
		return Vector3(m_fX / factor, m_fY / factor, m_fZ / factor);
}

const Vector3 Vector3::operator/(Vector3 vector) const
{
	return Vector3(m_fX / vector.x(), m_fY / vector.y(), m_fZ / vector.z());
}

Vector3& Vector3::operator=(const Vector3& vector)
{
	if (this == &vector)
		return *this;
	m_fX = vector.m_fX;
	m_fY = vector.m_fY;
	m_fZ = vector.m_fZ;
	return *this;
}

Vector3& Vector3::operator+=(const Vector3& vector)
{
	if (this == &vector)
	{
		m_fX *= 2;
		m_fY *= 2;
		m_fZ *= 2;
		return *this;
	}
	m_fX += vector.m_fX;
	m_fY += vector.m_fY;
	m_fZ += vector.m_fZ;
	return *this;
}
double &Vector3::operator[](const int i)
{
	switch (i)
	{
	case 0:	return m_fX; break;
	case 1: return m_fY; break;
	case 2:	return m_fZ; break;
	default:
		printf("Error with vector3!\n");
	}	
}

const double &Vector3::operator[](const int i) const
{
	switch (i)
	{
	case 0:	return m_fX; break;
	case 1: return m_fY; break;
	case 2:	return m_fZ; break;
	default:
		printf("Error with vector3!\n");
	}	
}

void Vector3::normalize()
{
	double length = module();
	if (length < ZERO)
		return;
	m_fX /= length;
	m_fY /= length;
	m_fZ /= length;
}

double Vector3::module() const
{
	return sqrt(m_fX * m_fX + m_fY * m_fY + m_fZ * m_fZ);
}
